package org.wx.herostory.services.processor.async;

import io.netty.util.NettyRuntime;
import lombok.extern.slf4j.Slf4j;
import org.wx.herostory.services.processor.MainMsgProcessor;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @description: 复杂耗时的任务处理器
 * @author: wangxun
 * @createDate: 2021/3/4
 * @version: 1.0
 */
@Slf4j
public class AsyncOperationProcessor {
    /**
     * 单例
     */
    static private final  AsyncOperationProcessor _instance = new AsyncOperationProcessor();


    /**
     * 运行的线程池的数量 cpu核心*2
     */
    static private int threadNum ;

    /**
     * 线程池
     */
    private final ExecutorService[] _esArray;

    private AsyncOperationProcessor(){
        /**
         * 初始化线程池，每个线程池就都是单线程
         */
        threadNum = Runtime.getRuntime().availableProcessors()*2;
        _esArray = new ExecutorService[threadNum];
        for (int i = 0; i < threadNum; i++) {
            final String theadName = "AsyncOperationProcessor [" + (i) + "]";
            _esArray[i]  = Executors.newSingleThreadExecutor((r)->{
                Thread thread = new Thread(r);
                thread.setName(theadName);
                return  thread;
            });
        }

    }

    /**
     * 获取单例
     * @return
     */
    static public AsyncOperationProcessor getInstance(){
        return _instance;
    }

    /**
     * 执行方法
     * @param op
     */
    public void process(IAsyncOperation op){
        if(null == op){
            return;
        }
        // 获取绑定Id 取绝对值
        int bindId = Math.abs(op.getBindId());
        int esIndex = bindId % threadNum;

        _esArray[esIndex].submit(()->{
            // 利用异步线程池去处理IO操作
            op.doAsync();
            // 将结果的处理放到主处理线程上，保证任务的入口和出口都是主任务处理（MainMsgProcessor）单线程的线程池
            MainMsgProcessor.getInstance().process(()->{
                op.doFinish();
            });
        });

    }
}
